package org.Yiran.timetale_re.item.tool.screwdriver.modules.items.function;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.Property;
import org.Yiran.timetale_re.block.crystal.base.CrystalBaseBlock;
import org.Yiran.timetale_re.item.tool.screwdriver.core.ScrewdriverItem;
import org.Yiran.timetale_re.item.tool.screwdriver.core.ScrewdriverModuleItem;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.enmu.ModuleCategory;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.enmu.ModuleType;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.type.RotationModule;
import org.jetbrains.annotations.NotNull;

/**
 * 基础朝向模块物品类
 * <p>
 * 该类实现了基础朝向模块，当安装到时英起子上时，
 * 可以改变方块的朝向。
 * </p>
 */
public class RotationModuleItem extends ScrewdriverModuleItem implements RotationModule {
    
    // ==============================
    // 构造方法
    // ==============================

    /**
     * 基础朝向模块物品构造函数
     * <p>
     * 创建一个基础朝向模块物品实例。
     * </p>
     */
    public RotationModuleItem() {
        super(
                ModuleLevel.BASIC,
                "tiername.level.basic"
        );
    }
    
    // ==============================
    // 物品属性方法
    // ==============================

    /**
     * 旋转方块
     * <p>
     * 旋转指定位置的方块朝向
     * </p>
     *
     * @param level 当前世界
     * @param pos   方块位置
     * @param state 方块状态
     * @return 是否成功旋转
     */
    @Override
    public boolean rotateBlock(Level level, BlockPos pos, BlockState state) {
        // 这个方法现在只在没有上下文时使用，保持原有逻辑
        // 检查是否为客户端，只在服务端执行实际逻辑
        if (level.isClientSide) {
            return true; // 客户端总是返回成功
        }
        
        // 检查方块是否为CrystalBaseBlock类型，如果是则不允许旋转
        if (isCrystalBaseBlock(state)) {
            return false;
        }
        
        // 检查方块是否为床类型，如果是则不允许旋转
        if (isBedBlock(state)) {
            return false;
        }
        
        // 尝试旋转方块，使用默认的北向
        return tryRotateBlock(level, pos, state);
    }
    
    /**
     * 旋转方块（带上下文）
     * <p>
     * 旋转指定位置的方块朝向，检查是否按住Shift键
     * </p>
     *
     * @param context 使用上下文
     * @return 交互结果
     */
    public InteractionResult rotateBlock(UseOnContext context) {
        Player player = context.getPlayer();
        ItemStack screwdriverStack = context.getItemInHand();
        
        // 检查是否按住Shift键
        if (player != null && player.isShiftKeyDown()) {
            // 检查方块是否为CrystalBaseBlock类型，如果是则不允许旋转
            BlockState currentState = context.getLevel().getBlockState(context.getClickedPos());
            if (isCrystalBaseBlock(currentState)) {
                return InteractionResult.PASS;
            }
            
            // 检查方块是否为床类型，如果是则不允许旋转
            if (isBedBlock(currentState)) {
                return InteractionResult.PASS;
            }
            
            // 检查起子是否有足够的能量（至少10FE）
            if (screwdriverStack.getItem() instanceof ScrewdriverItem screwdriver) {
                int energyStored = screwdriver.getEnergyStored(screwdriverStack);
                if (energyStored < 10) {
                    // 能量不足，不执行旋转
                    if (context.getLevel().isClientSide) {
                        player.displayClientMessage(Component.translatable("message.timetale_re.not_enough_energy"), false);
                    }
                    return InteractionResult.FAIL;
                }
                
                // 消耗10FE能量
                screwdriver.extractEnergy(screwdriverStack, 10, false);
            }
            
            // 按住Shift键时旋转方块，使其朝向点击的面
            return rotateBlockToFace(context);
        }
        return InteractionResult.PASS;
    }
    
    /**
     * 获取旋转后的方块状态
     * <p>
     * 根据原方块状态和点击的面计算旋转后的状态
     * </p>
     *
     * @param state 原始方块状态
     * @param clickedFace 点击的面
     * @return 旋转后的方块状态，如果无法旋转则返回null
     */
    private BlockState getRotatedBlockState(BlockState state, Direction clickedFace) {
        // 遍历所有属性，查找可以设置的方向属性
        BlockState directRotationState = tryDirectRotation(state, clickedFace);
        if (directRotationState != null) {
            return directRotationState;
        }
        
        // 如果点击的面不适用，则使用原来的循环方式
        return trySequentialRotation(state);
    }
    
    /**
     * 获取下一个方向
     * <p>
     * 根据当前方向和方向属性获取下一个方向
     * </p>
     *
     * @param currentDirection 当前方向
     * @param directionProperty 方向属性
     * @return 下一个方向
     */
    private Direction getNextDirection(Direction currentDirection, DirectionProperty directionProperty) {
        // 对于水平方向属性，使用顺时针旋转
        if (isHorizontalDirectionProperty(directionProperty)) {
            return currentDirection.getClockWise();
        }
        
        // 对于所有方向属性，循环遍历可能的值
        return getNextDirectionInCycle(currentDirection, directionProperty);
    }

    // ==============================
    // 辅助方法
    // ==============================

    /**
     * 检查方块是否为CrystalBaseBlock类型
     *
     * @param state 方块状态
     * @return 如果是CrystalBaseBlock类型返回true，否则返回false
     */
    private boolean isCrystalBaseBlock(BlockState state) {
        return state.getBlock() instanceof CrystalBaseBlock;
    }

    /**
     * 检查方块是否为床类型
     *
     * @param state 方块状态
     * @return 如果是床类型返回true，否则返回false
     */
    private boolean isBedBlock(BlockState state) {
        return state.getBlock() instanceof BedBlock;
    }

    /**
     * 尝试旋转方块到指定方向
     *
     * @param level 当前世界
     * @param pos   方块位置
     * @param state 方块状态
     * @return 是否成功旋转
     */
    private boolean tryRotateBlock(Level level, BlockPos pos, BlockState state) {
        BlockState rotatedState = getRotatedBlockState(state, Direction.NORTH);
        if (rotatedState != null && rotatedState != state) {
            // 应用新的方块状态
            level.setBlock(pos, rotatedState, 3);
            return true;
        }
        return false;
    }

    /**
     * 旋转方块使其朝向点击面
     *
     * @param context 使用上下文
     * @return 交互结果
     */
    private InteractionResult rotateBlockToFace(UseOnContext context) {
        BlockState currentState = context.getLevel().getBlockState(context.getClickedPos());
        BlockState rotatedState = getRotatedBlockState(currentState, context.getClickedFace());
        
        if (rotatedState != null && rotatedState != currentState) {
            // 应用新的方块状态
            context.getLevel().setBlock(context.getClickedPos(), rotatedState, 3);
            return InteractionResult.SUCCESS;
        }
        return InteractionResult.PASS;
    }

    /**
     * 尝试直接旋转到指定面
     *
     * @param state 方块状态
     * @param face  目标方向
     * @return 旋转后的方块状态，如果无法旋转则返回null
     */
    private BlockState tryDirectRotation(BlockState state, Direction face) {
        for (Property<?> prop : state.getProperties()) {
            if (prop instanceof DirectionProperty directionProperty) {
                // 检查点击的面是否适用于当前属性
                if (directionProperty.getPossibleValues().contains(face)) {
                    return state.setValue(directionProperty, face);
                }
            }
        }
        return null;
    }

    /**
     * 尝试顺序旋转方块
     *
     * @param state 方块状态
     * @return 旋转后的方块状态，如果无法旋转则返回null
     */
    private BlockState trySequentialRotation(BlockState state) {
        for (Property<?> prop : state.getProperties()) {
            if (prop instanceof DirectionProperty directionProperty) {
                if (state.hasProperty(directionProperty)) {
                    Direction currentDirection = state.getValue(directionProperty);
                    Direction nextDirection = getNextDirection(currentDirection, directionProperty);
                    if (nextDirection != currentDirection) {
                        return state.setValue(directionProperty, nextDirection);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 检查是否为水平方向属性
     *
     * @param directionProperty 方向属性
     * @return 如果是水平方向属性返回true，否则返回false
     */
    private boolean isHorizontalDirectionProperty(DirectionProperty directionProperty) {
        return directionProperty.getPossibleValues().contains(Direction.NORTH) &&
               directionProperty.getPossibleValues().contains(Direction.EAST) &&
               directionProperty.getPossibleValues().contains(Direction.SOUTH) &&
               directionProperty.getPossibleValues().contains(Direction.WEST);
    }

    /**
     * 在可能的方向中获取下一个方向
     *
     * @param currentDirection 当前方向
     * @param directionProperty 方向属性
     * @return 下一个方向
     */
    private Direction getNextDirectionInCycle(Direction currentDirection, DirectionProperty directionProperty) {
        Direction[] directions = directionProperty.getPossibleValues().toArray(new Direction[0]);
        for (int i = 0; i < directions.length; i++) {
            if (directions[i] == currentDirection) {
                return directions[(i + 1) % directions.length];
            }
        }
        // 默认返回当前方向
        return currentDirection;
    }

    /**
     * 获取物品显示名称
     * <p>
     * 返回该模块物品的显示名称。
     * </p>
     *
     * @param stack 物品栈
     * @return 显示名称
     */
    @Override
    public @NotNull Component getName(@NotNull ItemStack stack) {
        return Component.translatable("item.timetale_re.rotation_module");
    }
    
    /**
     * 获取模块的唯一标识符
     *
     * @return 模块ID
     */
    @Override
    public String getModuleId() {
        return "rotation_module";
    }
    
    /**
     * 获取模块的显示名称
     *
     * @return 模块名称
     */
    @Override
    public Component getDisplayName() {
        return Component.translatable("item.timetale_re.rotation_module");
    }
    
    /**
     * 获取模块类型
     *
     * @return 模块类型
     */
    @Override
    public ModuleType getModuleType() {
        return ModuleType.ROTATION;
    }
    
    /**
     * 获取模块分类
     *
     * @return 模块分类
     */
    @Override
    public ModuleCategory getModuleCategory() {
        return ModuleCategory.FUNCTION;
    }

    @Override
    public ScrewdriverModuleItem.ModuleLevel getModuleLevel() {
        return ScrewdriverModuleItem.ModuleLevel.BASIC;
    }
}